home *** CD-ROM | disk | FTP | other *** search
/ BCI NET 2 / BCI NET 2.iso / archives / programming / c / hce.lha / HCE / LibSource / clib / Stdio / src / scanf.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-09-02  |  5.7 KB  |  328 lines

  1. #include <stdio.h>
  2. #include <ctype.h>
  3. #define    FALSE    (0)
  4. #define TRUE    (!FALSE)
  5.  
  6. /* From the Hcc.lib by Detlef Wurkner, Placed here by J.P.*/
  7. /* Modified by J.P. */
  8. /* This version of scanf does not suport floats, if you need float scanf */
  9. /* link the math.lib as first library in list. */
  10.  
  11. static char    _numstr[] = "0123456789ABCDEF";
  12.  
  13. /* #define    skip()    do{c=(*get)(ip); if (c<1) goto done;}while(isspace(c))*/
  14.  
  15. #define    skip()    while(isspace(c)) { if ((c=(*get)(ip))<1) goto done; }
  16.  
  17.  
  18. _scanf(ip, get, unget, fmt, args)
  19.     register unsigned char *ip;
  20.     int (*get)();
  21.     int (*unget)();
  22.     register unsigned char *fmt;
  23.     char **args;
  24.  
  25.     {
  26.     register long n;
  27.     register int c, width, lval, cnt = 0;
  28.  
  29. /* ADDED BY TETISOFT */
  30.     int sval;
  31.  
  32.     int store, neg, base, wide1, endnull, rngflag, c2;
  33.     register unsigned char *p;
  34.     unsigned char delim[128], digits[17], *q;
  35.     char *strchr(), *strcpy();
  36.     long frac, expo;
  37.     int eneg, fraclen, fstate, trans;
  38.     double fx, fp_scan();
  39.  
  40.     if (!*fmt)
  41.         return(0);
  42.  
  43.     c = (*get)(ip);
  44.     while(c > 0)
  45.         {
  46.         store = FALSE;
  47.         if (*fmt == '%')
  48.             {
  49.             n    = 0;
  50.             width    = -1;
  51.             wide1    = 1;
  52.             base    = 10;
  53.             lval    = FALSE;
  54.  
  55. /* ADDED BY TETISOFT */
  56.             sval    = FALSE;
  57.  
  58.             store    = TRUE;
  59.             endnull    = TRUE;
  60.             neg    = -1;
  61.  
  62.             strcpy(delim,  "\011\012\013\014\015 ");
  63.             strcpy(digits, _numstr); /* "01234567890ABCDEF" */
  64.  
  65.             if (fmt[1] == '*')
  66.                 {
  67.                 endnull = store = FALSE;
  68.                 ++fmt;
  69.                 }
  70.  
  71.             while (isdigit(*++fmt))        /* width digit(s) */
  72.                 {
  73.                 if (width == -1)
  74.                     width = 0;
  75.                 wide1 = width = (width * 10) + (*fmt - '0');
  76.                 }
  77.             --fmt;
  78. fmtnxt:
  79.             ++fmt;
  80.             switch(tolower(*fmt))    /* tolower() is a MACRO! */
  81.                 {
  82.                 case '*':
  83.                     endnull = store = FALSE;
  84.                     goto fmtnxt;
  85.  
  86.                 case 'l':    /* long data */
  87.                     lval = TRUE;
  88.  
  89. /* ADDED BY TETISOFT */            goto fmtnxt;
  90.  
  91. /* for compatability --> */    case 'h':    /* short data */
  92.  
  93. /* ADDED BY TETISOFT */            sval = TRUE;
  94.  
  95.                     goto fmtnxt;
  96.  
  97.                 case 'i':    /* any-base numeric */
  98.                     base = 0;
  99.                     goto numfmt;
  100.  
  101.                 case 'b':    /* unsigned binary */
  102.                     base = 2;
  103.                     goto numfmt;
  104.  
  105.                 case 'o':    /* unsigned octal */
  106.                     base = 8;
  107.                     goto numfmt;
  108.  
  109.                 case 'x':    /* unsigned hexadecimal */
  110.                     base = 16;
  111.                     goto numfmt;
  112.  
  113.                 case 'd':    /* SIGNED decimal */
  114.                     neg = FALSE;
  115.                     /* FALL-THRU */
  116.  
  117.                 case 'u':    /* unsigned decimal */
  118. numfmt:                    skip();
  119.  
  120.                     if (isupper(*fmt))
  121.                         lval = TRUE;
  122.  
  123.                     if (!base)
  124.                         {
  125.                         base = 10;
  126.                         neg = FALSE;
  127.                         if (c == '%')
  128.                             {
  129.                             base = 2;
  130.                             goto skip1;
  131.                             }
  132.                         else if (c == '0')
  133.                             {
  134.                             c = (*get)(ip);
  135.                             if (c < 1)
  136.                                 goto savnum;
  137.                             if ((c != 'x')
  138.                              && (c != 'X'))
  139.                                 {
  140.                                 base = 8;
  141.                                 digits[8]= '\0';
  142.                                 goto zeroin;
  143.                                 }
  144.                             base = 16;
  145.                             goto skip1;
  146.                             }
  147.                         }
  148.  
  149.                     if ((neg == FALSE) && (base == 10)
  150.                      && ((neg = (c == '-')) || (c == '+')))
  151.                         {
  152. skip1:
  153.                         c = (*get)(ip);
  154.                         if (c < 1)
  155.                             goto done;
  156.                         }
  157.  
  158.                     digits[base] = '\0';
  159.                     p = ((unsigned char *)
  160.                         strchr(digits,toupper(c)));
  161.  
  162.                     if ((!c || !p) && width)
  163.                         goto done;
  164.  
  165.                     while (p && width-- && c)
  166.                         {
  167.                         n = (n * base) + (p - digits);
  168.                         c = (*get)(ip);
  169. zeroin:
  170.                         p = ((unsigned char *)
  171.                         strchr(digits,toupper(c)));
  172.                         }
  173. savnum:
  174.                     if (store)
  175.                         {
  176.                         p = ((unsigned char *) *args);
  177.                         if (neg == TRUE)
  178.                             n = -n;
  179.                         if (lval)
  180.                             *((long*) p) = n;
  181.                         else
  182.  
  183. /* ADDED BY TETISOFT */                if (sval)
  184.                             *((short*) p) = n;
  185.                         else
  186.  
  187.                             *((int *) p) = n;
  188.                         ++cnt;
  189.                         }
  190.                     break;
  191.  
  192.                 case 'e':    /* float */
  193.                 case 'f':
  194.                 case 'g':        /* floats removed J.P. */
  195.                                           goto done;
  196.  
  197.                 case 'c':    /* character data */
  198.                     width = wide1;
  199.                     endnull    = FALSE;
  200.                     delim[0] = '\0';
  201.                     goto strproc;
  202.  
  203.                 case '[':    /* string w/ delimiter set */
  204.  
  205.                     /* get delimiters */
  206.                     p = delim;
  207.  
  208.                     if (*++fmt == '^')
  209.                         fmt++;
  210.                     else
  211.                         lval = TRUE;
  212.  
  213.                     rngflag = 2;
  214.                     if ((*fmt == ']') || (*fmt == '-'))
  215.                         {
  216.                         *p++ = *fmt++;
  217.                         rngflag = FALSE;
  218.                         }
  219.  
  220.                     while (*fmt != ']')
  221.                         {
  222.                         if (*fmt == '\0')
  223.                             goto done;
  224.                         switch (rngflag)
  225.                             {
  226.                             case TRUE:
  227.                             c2 = *(p-2);
  228.                             if (c2 <= *fmt)
  229.                                 {
  230.                                 p -= 2;
  231.                                 while (c2 < *fmt)
  232.                                     *p++ = c2++;
  233.                                 rngflag = 2;
  234.                                 break;
  235.                                 }
  236.                             /* fall thru intentional */
  237.  
  238.                             case FALSE:
  239.                             rngflag = (*fmt == '-');
  240.                             break;
  241.  
  242.                             case 2:
  243.                             rngflag = FALSE;
  244.                             }
  245.  
  246.                         *p++ = *fmt++;
  247.                         }
  248.  
  249.                     *p = '\0';
  250.                     goto strproc;
  251.  
  252.                 case 's':    /* string data */
  253.                     skip();
  254. strproc:
  255.                     /* process string */
  256.                     p = ((unsigned char *) *args);
  257.  
  258.                     /* if the 1st char fails, match fails */
  259.                     if (width)
  260.                         {
  261.                         q = ((unsigned char *)
  262.                             strchr(delim, c));
  263.                         if((c < 1)
  264.                         || (lval ? !q : (int) q))
  265.                             {
  266.                             if (endnull)
  267.                                 *p = '\0';
  268.                             goto done;
  269.                             }
  270.                         }
  271.  
  272.                     for (;;) /* FOREVER */
  273.                         {
  274.                         if (store)
  275.                             *p++ = c;
  276.                         if (((c = (*get)(ip)) < 1) ||
  277.                             (--width == 0))
  278.                             break;
  279.  
  280.                         q = ((unsigned char *)
  281.                             strchr(delim, c));
  282.                         if (lval ? !q : (int) q)
  283.                             break;
  284.                         }
  285.  
  286.                     if (store)
  287.                         {
  288.                         if (endnull)
  289.                             *p = '\0';
  290.                         ++cnt;
  291.                         }
  292.                     break;
  293.  
  294.                 case '\0':    /* early EOS */
  295.                     --fmt;
  296.                     /* FALL THRU */
  297.  
  298.                 default:
  299.                     goto cmatch;
  300.                 }
  301.             }
  302.         else if (isspace(*fmt))        /* skip whitespace */
  303.             {
  304.             skip();
  305.             }
  306.         else 
  307.             {            /* normal match char */
  308. cmatch:
  309.             if (c != *fmt) 
  310.                 break;
  311.             c = (*get)(ip);
  312.             }
  313.  
  314.         if (store)
  315.             args++;
  316.  
  317.         if (!*++fmt)
  318.             break;
  319.         }
  320.  
  321. done:                        /* end of scan */
  322.     if ((c < 0) && (cnt == 0))
  323.         return(EOF);
  324.  
  325.     (*unget)(c, ip);
  326.     return(cnt);
  327.     }
  328.